﻿#ifndef MAPENGINEDATA_H
#define MAPENGINEDATA_H

#include <QObject>

#include "CachedTileSet.h"

//class CachedTileSet;

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Tile
class Tile
{
public:
    Tile()
        : _x(0)
        , _y(0)
        , _z(0)
        , _set(UINT64_MAX)
        , _type("Invalid")
    {
    }
    Tile(const QString& hash) : _hash(hash) { }

    enum TyleState {
        StatePending = 0,
        StateDownloading,
        StateError,
        StateComplete
    };

    QString    hash() const { return _hash; }
    QByteArray img() const { return _img; }
    int        size() const { return _size; }
    QString    format() const { return _format; }
    int        x() const { return _x; }
    int        y() const { return _y; }
    int        z() const { return _z; }
    QString    type() const { return _type; }
    int        mapId() const { return _mapId; }

    void setImg(const QByteArray& img) { _img = img; }
    void setSize(int size) { _size = size; }
    void setFormat(const QString& format) { _format = format; }
    void setX(int x) { _x = x; }
    void setY(int y) { _y = y; }
    void setZ(int z) { _z = z; }
    void setType(const QString& type) { _type = type; }
    void setMapId(int id) { _mapId = id; }
    void setTileSet  (qulonglong set) { _set = set;  }
    void                setHash     (const QString& hash) { _hash = hash; }

private:
    QString    _hash;       //由 x,y,zoom,type,计算得到的哈希值,具有tile的唯一性
    QByteArray _img;        //瓦片具体数据
    int        _size = 0;   //瓦片数据大小
    QString    _format;     //瓦片格式
    int        _x    = 0;   //瓦片x
    int        _y    = 0;   //瓦片y
    int        _z = 0;      //瓦片zoom
    QString    _type;       //地图类型
    int        _mapId = 0;  //地图类型ID
    qulonglong  _set;
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CacheTile
class CacheTile : public QObject
{
    Q_OBJECT
public:
    CacheTile    (const QString& hash, const QByteArray& img, const QString& format, const QString& type, qulonglong set = UINT64_MAX)
        : _set(set)
        , _hash(hash)
        , _img(img)
        , _format(format)
        , _type(type)
    {}
    CacheTile    (const QString hash, qulonglong set)
        : _set(set)
        , _hash(hash)
    {
    }

    qulonglong          set     () const{ return _set;   }
    QString             hash    () { return _hash;  }
    QByteArray          img     () { return _img;   }
    QString             format  () { return _format;}
    QString type    () { return _type; }

private:
    qulonglong  _set;
    QString     _hash;
    QByteArray  _img;
    QString     _format;
    QString _type;
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MapTask
class MapTask : public QObject
{
    Q_OBJECT
public:

    enum TaskType {
        taskInit,
        taskTestInternet,
        taskCacheTile,
        taskFetchTile,
        taskFetchTileSets,
        taskCreateTileSet,
        taskGetTileDownloadList,
        taskUpdateTileDownloadState,
        taskDeleteTileSet,
        taskRenameTileSet,
        taskPruneCache,
        taskReset,
        taskExport,
        taskImport,
    };
    Q_ENUM(TaskType)

    MapTask(TaskType type): m_type(type) {}
    virtual ~MapTask() {}

    virtual TaskType type() { return m_type; }
    void setError(QString errorString = QString()) { emit error(m_type, errorString); }

signals:
    void error          (MapTask::TaskType type, QString errorString);

private:
    TaskType m_type;
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TestInternetTask
class TestInternetTask : public MapTask
{
    Q_OBJECT
public:
    TestInternetTask() : MapTask(MapTask::taskTestInternet) { }
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SaveTileTask
// tag:useCacheTile
class SaveTileTask : public MapTask
{
    Q_OBJECT
public:
    SaveTileTask(CacheTile* tile): MapTask(MapTask::taskCacheTile) , _tile(tile) {}
    ~SaveTileTask()
    {
        if (_tile) {
            delete _tile;
            _tile = nullptr;
        }
    }

    CacheTile*   tile() { return _tile; }

private:
    CacheTile*   _tile;
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FetchTileTask
// tag:useCacheTile
class FetchTileTask : public MapTask
{
    Q_OBJECT
public:
    FetchTileTask(const QString& hash): MapTask(MapTask::taskFetchTile), _hash(hash) {}
    ~FetchTileTask() = default;

    void setTileFetched(CacheTile* tile) { emit tileFetched(tile); }
    QString hash() { return _hash; }

signals:
    void tileFetched(CacheTile* tile);

private:
    QString _hash;
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FetchTileSetTask
class FetchTileSetTask : public MapTask
{
    Q_OBJECT
public:
    FetchTileSetTask()
        : MapTask(MapTask::taskFetchTileSets)
    {}

    void setTileSetFetched(CachedTileSet* tileSet)
    {
        emit tileSetFetched(tileSet);
    }

signals:
    void            tileSetFetched  (CachedTileSet* tileSet);
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CreateTileSetTask
class CreateTileSetTask : public MapTask
{
    Q_OBJECT
public:
    CreateTileSetTask(CachedTileSet* tileSet)
        : MapTask(MapTask::taskCreateTileSet)
        , _tileSet(tileSet)
        , _saved(false)
    {}
    ~CreateTileSetTask() {
        //-- If not sent out, delete it
        if(!_saved && _tileSet)
            delete _tileSet;
    }

    CachedTileSet*   tileSet () { return _tileSet; }
    void setTileSetSaved()
    {
        //-- Flag as saved. Signalee wll maintain it.
        _saved = true;
        emit tileSetSaved(_tileSet);
    }

signals:
    void tileSetSaved   (CachedTileSet* tileSet);

private:
    CachedTileSet*  _tileSet;
    bool            _saved;
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ GetTileDownloadListTask
class GetTileDownloadListTask : public MapTask
{
    Q_OBJECT
public:
    GetTileDownloadListTask(qulonglong setID, int count)
        : MapTask(MapTask::taskGetTileDownloadList)
        , _setID(setID)
        , _count(count)
    {}

    qulonglong  setID() const{ return _setID; }
    int         count() const{ return _count; }

    void setTileListFetched(QList<Tile*> tiles)
    {
        emit tileListFetched(tiles);
    }

signals:
    void            tileListFetched  (QList<Tile*> tiles);

private:
    qulonglong  _setID;
    int         _count;
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UpdateTileDownloadStateTask
class UpdateTileDownloadStateTask : public MapTask
{
    Q_OBJECT
public:
    UpdateTileDownloadStateTask(qulonglong setID, Tile::TyleState state, const QString& hash)
        : MapTask(MapTask::taskUpdateTileDownloadState)
        , _setID(setID)
        , _state(state)
        , _hash(hash)
    {}

    QString             hash    () { return _hash; }
    qulonglong          setID   () const{ return _setID; }
    Tile::TyleState     state   () { return _state; }

private:
    qulonglong          _setID;
    Tile::TyleState     _state;
    QString             _hash;
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DeleteTileSetTask
class DeleteTileSetTask : public MapTask
{
    Q_OBJECT
public:
    DeleteTileSetTask(qulonglong setID)
        : MapTask(MapTask::taskDeleteTileSet)
        , _setID(setID)
    {}

    qulonglong  setID() const{ return _setID; }

    void setTileSetDeleted()
    {
        emit tileSetDeleted(_setID);
    }

signals:
    void tileSetDeleted(qulonglong setID);

private:
    qulonglong  _setID;
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ RenameTileSetTask
class RenameTileSetTask : public MapTask
{
    Q_OBJECT
public:
    RenameTileSetTask(qulonglong setID, QString newName)
        : MapTask(MapTask::taskRenameTileSet)
        , _setID(setID)
        , _newName(newName)
    {}

    qulonglong  setID   () const{ return _setID; }
    QString     newName () { return _newName; }

private:
    qulonglong  _setID;
    QString     _newName;
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ PruneCacheTask
class PruneCacheTask : public MapTask
{
    Q_OBJECT
public:
    PruneCacheTask(quint64 amount)
        : MapTask(MapTask::taskPruneCache)
        , _amount(amount)
    {}

    quint64  amount() const{ return _amount; }

    void setPruned()
    {
        emit pruned();
    }

signals:
    void pruned();

private:
    quint64  _amount;
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ResetTask
class ResetTask : public MapTask
{
    Q_OBJECT
public:
    ResetTask()
        : MapTask(MapTask::taskReset)
    {}

    void setResetCompleted()
    {
        emit resetCompleted();
    }

signals:
    void resetCompleted();
};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ExportTileTask
class ExportTileTask : public MapTask
{
    Q_OBJECT
public:
    ExportTileTask(QVector<CachedTileSet*> sets, QString path)
        : MapTask(MapTask::taskExport)
        , _sets(sets)
        , _path(path)
    {}
    ~ExportTileTask() = default;

    QVector<CachedTileSet*> sets() { return _sets; }
    QString                 path() { return _path; }

    void setExportCompleted()
    {
        emit actionCompleted();
    }

    void setProgress(int percentage)
    {
        emit actionProgress(percentage);
    }

private:
    QVector<CachedTileSet*>  _sets;
    QString                  _path;

signals:
    void actionCompleted        ();
    void actionProgress         (int percentage);

};

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ImportTileTask
class ImportTileTask : public MapTask
{
    Q_OBJECT
public:
    ImportTileTask(QString path, bool replace)
        : MapTask(MapTask::taskImport)
        , _path(path)
        , _replace(replace)
    {}
    ~ImportTileTask() = default;

    QString                    path     () { return _path; }
    bool                       replace  () const{ return _replace; }

    void setImportCompleted()
    {
        emit actionCompleted();
    }

    void setProgress(int percentage)
    {
        emit actionProgress(percentage);
    }

private:
    QString                     _path;
    bool                        _replace;

signals:
    void actionCompleted        ();
    void actionProgress         (int percentage);

};

#endif // MAPENGINEDATA_H
